uniform vec4 lightPosition;
uniform vec4 eyePosition;
uniform sampler2D bottomTex;
uniform sampler2D causticsTex;
uniform bool transparent;

const vec3 specularColor = vec3(0.5);
const vec3 waterColor = vec3(0.2, 0.5, 0.7);
const float ambient = 0.2;
const float externalIndex = 1.0003;
const float internalIndex = 1.33;
const float zBottom = -0.2;

varying vec4 vertex;
varying vec3 normal;

void myRefract(in vec3 incident, in vec3 normal,
			   out vec3 refraction, out float transmittance)
{
	float eta = externalIndex / internalIndex;
	float cos_theta1 = abs(dot(incident, normal));
	float cos_theta2 = sqrt(1.0 - eta * eta * (1.0 - cos_theta1 * cos_theta1));
	refraction = incident * eta - normal * (cos_theta2 - eta * cos_theta1);

	float fresnel_rs = (internalIndex * cos_theta2 - externalIndex * cos_theta1) /
					   (internalIndex * cos_theta2 + externalIndex * cos_theta1);

	float fresnel_rp = (internalIndex * cos_theta1 - externalIndex * cos_theta2) /
					   (internalIndex * cos_theta1 + externalIndex * cos_theta2);

	transmittance = 1.0 - (fresnel_rs * fresnel_rs + fresnel_rp * fresnel_rp) * 0.5;
}

void main(void)
{
	vec3 ecPosition = vec3(gl_ModelViewMatrix * vertex);
	vec3 lightPos = vec3(gl_ModelViewMatrix * lightPosition);
	vec3 tnorm = normalize(gl_NormalMatrix * normal);
	vec3 lightVec = normalize(lightPos - ecPosition);
	vec3 reflectVec = reflect(-lightVec, tnorm);
	vec3 viewVec = normalize(-ecPosition);
	float diffuse = max(dot(lightVec, tnorm), 0.0);
	float specular = 0.0;
	
	if (diffuse > 0.0)
	{
		specular = max(dot(reflectVec, viewVec), 0.0);
		specular = pow(specular, 128.0);
	}
	
	vec3 eyeVec = normalize(vec3(vertex - eyePosition));
	vec3 waterRefract;
	float waterTrans;
	myRefract(eyeVec, normal, waterRefract, waterTrans);
	vec2 texCoord; 
	texCoord.s = vertex.x + (zBottom - vertex.z) * waterRefract.x / waterRefract.z;
	texCoord.t = vertex.y + (zBottom - vertex.z) * waterRefract.y / waterRefract.z;

	vec3 diffuseColor;
	if (transparent) {
		if (texCoord.s > 0.0 && texCoord.s < 1.0 && texCoord.t > 0.0 && texCoord.t < 1.0) {
			vec3 bottomColor = vec3(texture2D(bottomTex, texCoord));
			vec3 causticsColor = vec3(texture2D(causticsTex, texCoord));
			float diffuseBottom = max(-normalize(waterRefract).z, 0.0);
			diffuseColor = mix(waterColor, (bottomColor * 0.6 + causticsColor) * diffuseBottom, waterTrans);
		}
		else {
			diffuseColor = mix(waterColor, vec3(0.0), waterTrans);
		}
	}
	else
		diffuseColor = waterColor;
	
	vec3 color = diffuseColor * (diffuse + ambient) + specularColor * specular;
	
	gl_FragColor = vec4(color, 1.0);
}
